#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QByteArray>
#include <QtCore/QEvent>
#include <QtCore/QThread>
#include <QtGui/QKeyEvent>
#include <QtGui/QAction>
#include <abstractformwindowcursor.h>
#include <abstractformwindowtool.h>

#include "formeditorw.h"
#include "resourceeditorw.h"
#include "widgetboxw.h"

#include "formwindoww.h"

using namespace SharedTools;

FormWindowW::FormWindowW(QWidget *parent) : WidgetHost(parent), m_fwm(0), m_core(0), m_initialized(0)
{

}

void FormWindowW::initialize()
{
    if (!m_initialized)
    {
        m_initialized = true;
        FormEditorW::instance()->initialize();

        m_lastDirtyFlag = true;

        FormEditorW::instance()->addFormWindowW(this);

        m_fwm = FormEditorW::instance()->formEditor()->formWindowManager();
        m_core = FormEditorW::instance()->formEditor();
        m_core->setTopLevel(parentWidget());

        QDesignerFormWindowInterface *form = m_fwm->createFormWindow(this);

        setFormWindow(form);

        connect(form, SIGNAL(selectionChanged()), this, SLOT(formSelectionChanged()));
        connect(this, SIGNAL(formWindowSizeChanged(int,int)), this, SLOT(formSizeChanged(int,int)));
        connect(form, SIGNAL(resourceFilesChanged()), this, SIGNAL(resourceFilesChanged()));
        connect(form, SIGNAL(changed()), this, SLOT(formChanged()));

        if (!FormEditorW::instance()->updateTopLevel())
            FormEditorW::instance()->formEditor()->setTopLevel(form);

        installEventFilter(this);
    }
}

bool FormWindowW::initializeJambiPlugins(const QString &jambiBase, const QString &jambiPluginPath, const QString &customWidgetClassPath, const QString &resourcePath, const QString &jvm)
{
    return FormEditorW::instance()->initializeJambiPlugins(jambiBase, jambiPluginPath, customWidgetClassPath, resourcePath, jvm);
}

void FormWindowW::updateCustomWidgetLocation(const QString &path)
{
    WidgetBoxW *w = WidgetBoxW::instance();

    if (w != 0)
    {
        w->updateCustomWidgetLocation(path);
    }
}

bool FormWindowW::eventFilter(QObject *watched, QEvent *e)
{
    if (watched == this && e->type() == QEvent::ShortcutOverride)
    {
        QKeyEvent *k = static_cast<QKeyEvent *>(e);
        QKeySequence ks(k->key() + k->modifiers());

        if (!ks.isEmpty())
        {
            FormEditorW *fe = FormEditorW::instance();

            for (int i = 7; i <= fe->lastAction(); ++i)
            {
                if (fe->idToAction(i)->shortcut() == ks)
                {
                    fe->idToAction(i)->trigger();
                    return true;
                }
            }
        }
    }
    return WidgetHost::eventFilter(watched, e);
}

FormWindowW::~FormWindowW()
{
    FormEditorW::instance()->updateTopLevel(formWindow());
    FormEditorW::instance()->removeFormWindowW(this);
}

void FormWindowW::open(QString fileName)
{
    QFile file(fileName);
    QDesignerFormWindowInterface *form = formWindow();
    form->setFileName(fileName);

    if (file.open(QIODevice::ReadOnly))
    {
        form->setContents(&file);
        file.close();
    }

    form->setDirty(false);
}

void FormWindowW::close()
{

}

void FormWindowW::setObjectName(const QString &objectName)
{
    QWidget *mc = formWindow()->mainContainer();

    if (mc)
        mc->setObjectName(objectName);
}

bool FormWindowW::save()
{
    return save(formWindow()->fileName());
}

bool FormWindowW::saveAs(QString fileName)
{
    if (!save(fileName))
        return false;

    formWindow()->setFileName(fileName);
    return true;
}

bool FormWindowW::save(QString fileName)
{
    QDesignerFormWindowInterface *form = formWindow();
    QWidget *mc = form->mainContainer();

    if (mc)
    {
        if (mc->objectName().isEmpty())
            mc->setObjectName(QFileInfo(fileName).baseName());
    }

    QFile f(fileName);

    if (!f.open(QFile::WriteOnly))
        return false;

    QByteArray utf8Array = form->contents().toUtf8();

    if (f.write(utf8Array, utf8Array.size()) != utf8Array.size())
        return false;

    form->setDirty(false);
    return true;
}

bool FormWindowW::isDirty()
{
    m_lastDirtyFlag = formWindow()->isDirty();
    return m_lastDirtyFlag;
}

void FormWindowW::formChanged()
{
    if (m_lastDirtyFlag != formWindow()->isDirty())
    {
        Q_EMIT updateDirtyFlag();
    }
}

int FormWindowW::actionCount()
{
    return FormEditorW::instance()->lastAction()+1;
}

int FormWindowW::staticActionCount()
{
    return FormEditorW::LastStaticAction+1;
}

QString FormWindowW::actionName(int id)
{
    if (QAction *act = FormEditorW::instance()->idToAction(id))
        return act->text();

    return QString("unknown id");
}

QString FormWindowW::actionToolTip(int id)
{
    if (QAction *act = FormEditorW::instance()->idToAction(id))
        return act->toolTip();

    return QString("error");
}

void FormWindowW::actionTrigger(int id)
{
    static bool recursion_block = false;

    if (recursion_block || !(recursion_block = true))
    	return;

    if (QAction *act = FormEditorW::instance()->idToAction(id))
        act->trigger();

    recursion_block = false;
}

bool FormWindowW::isEnabled(int id)
{
    if (QAction *act = FormEditorW::instance()->idToAction(id))
        return act->isEnabled();

    return false;
}

void FormWindowW::setActiveFormWindow()
{
    m_fwm->setActiveFormWindow(formWindow());
    formWindow()->setFocus();
}

int FormWindowW::toolCount()
{
    return formWindow()->toolCount();
}

QString FormWindowW::toolName(int index)
{
    QDesignerFormWindowToolInterface *fwtool = formWindow()->tool(index);

    if (fwtool->action())
        return fwtool->action()->text();

    return QString("error");
}

QString FormWindowW::toolToolTip(int index)
{
    QDesignerFormWindowToolInterface *fwtool = formWindow()->tool(index);

    if (fwtool->action())
        return fwtool->action()->toolTip();

    return QString("error");
}

int FormWindowW::currentTool()
{
    return formWindow()->currentTool();
}

void FormWindowW::setCurrentTool(int index)
{
    formWindow()->setCurrentTool(index);
}

void FormWindowW::formSizeChanged(int /*w*/, int /*h*/)
{
    formWindow()->setDirty(true);
    formChanged();
    formWindow()->emitSelectionChanged();
}

void FormWindowW::formSelectionChanged()
{
    QDesignerFormWindowCursorInterface *cursor = 0;
    QDesignerFormWindowInterface *form = formWindow();

    cursor = form->cursor();

    if (form == m_fwm->activeFormWindow() && cursor && cursor->isWidgetSelected(form->mainContainer()))
    {
        updateFormWindowSelectionHandles(true);

        bool blocked = form->blockSignals(true);
        Q_EMIT checkActiveWindow();
        form->blockSignals(blocked);
    }
    else
    {
        updateFormWindowSelectionHandles(false);
    }
}

void FormWindowW::updateJambiResourcePath(const QString &resourcePath)
{
    ResourceEditorW::instance()->updateResources(resourcePath);
}

QString FormWindowW::pluginFailureString() const
{
    return FormEditorW::instance()->pluginFailureString();
}

/*void FormWindowW::mouseReleaseEvent(QMouseEvent *)
{
    FormEditorW::instance()->unselectAllFormWindows();
}*/
